﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;

namespace GeneratePE {
    internal class ProcedureHelper {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="tableName">要生成 Procedures 的表名称</param>
        public ProcedureHelper(string tableName) {
            this.TableName = tableName;
            this.GenerateDate = DateTime.Now.ToShortDateString();
            this.InitData();
        }
        /// <summary>
        /// 生成 Procedures
        /// </summary>
        /// <returns>List</returns>
        public string Generate() {
            if (this.DictionaryKey.Count == 0) { return "未提供主键！"; }

            string templateValue = GenerateHelper.GetTemplateContent(Resources.SqlProcedure);
            Dictionary<string, string> d = new Dictionary<string, string>(13);
            d.Add("tablename", this.TableName);
            d.Add("generatedate", this.GenerateDate);
            d.Add("primarykeyparameter", this.OrganizKey(GenerateType.Parameter, 1));
            d.Add("createparameter", this.OrganizColumn(GenerateType.Parameter, 1));
            d.Add("fieldtext", this.OrganizColumn(GenerateType.Insert, 3));
            d.Add("fieldvalue", this.OrganizColumn(GenerateType.InsertAT, 3));
            d.Add("updateparameter", this.OrganizColumn(GenerateType.Parameter, 1));
            d.Add("updatefielddata", this.OrganizColumn(GenerateType.Update, 3));
            d.Add("primarykeyfieldtext", this.OrganizKey(GenerateType.Insert, 3));
            d.Add("primarykeyfielddata", this.OrganizKeyData());

            foreach (string key in d.Keys) {
                templateValue = GenerateHelper.RegexReplace(
                    string.Format(@"\${0}\$", key), templateValue, d[key]);
            }
            return templateValue;
        }

        #region Properties

        // 生成日期
        private string GenerateDate { get; set; }
        // 表名
        private string TableName { get; set; }
        // 主键列
        private Dictionary<string, string> DictionaryKey { get; set; }
        // 除了主键的其它列
        private Dictionary<string, string> DictionaryColumn { get; set; }

        #endregion

        #region Private Methods

        // 初始化数据
        private void InitData() {
            DataTable dt = GenerateHelper.LoadTableSchema(this.TableName);

            var pkey = new Dictionary<string, string>();
            var column = new Dictionary<string, string>();
            foreach (DataRow dr in dt.Rows) {
                string name = dr["Name"].ToString();
                string value = this.OrganizDbType(dr);
                if (Convert.ToBoolean(dr["PrimaryKey"])) {
                    if (!pkey.ContainsKey(name)) {
                        pkey.Add(name, value);
                        continue;
                    }
                }
                if (!column.ContainsKey(name)) { column.Add(name, value); }
            }

            this.DictionaryKey = pkey;
            this.DictionaryColumn = column;
        }
        // 组织数据库参数类型
        private string OrganizDbType(DataRow dr) {
            const string allowLength = "xml,varchar,char,nchar,nvarchar";
            string type = dr["Type"].ToString().ToLower();
            bool isNull = Convert.ToBoolean(dr["Nullable"]);
            string value = type;
            if (allowLength.Contains(type)) {
                if (!dr["Length"].Equals(DBNull.Value)) {
                    int length = Convert.ToInt32(dr["Length"]);
                    value = string.Format("{0}({1})", type, length > 0 ? length.ToString() : "max");
                }
            }
            return value;
        }
        // 构靠替换字符串 PrimaryKey
        private string OrganizKey(GenerateType gt, int tabNum) {
            return this.JoinByDictionary(this.DictionaryKey, gt, tabNum);
        }
        // 构靠替换字符串（多个主键） PrimaryKey data
        private string OrganizKeyData() {
            string value = string.Empty;
            foreach (string key in this.DictionaryKey.Keys) {
                value += "," + string.Format("{0}=@{0}", key);
            }
            return value.Substring(1).Replace(",", " AND ");
        }
        // 构靠替换字符串 Columns
        private string OrganizColumn(GenerateType gt, int tabNum) {
            return this.JoinByDictionary(this.DictionaryColumn, gt, tabNum);
        }
        /// <summary>
        /// 根据指定的类型连接参数
        /// </summary>
        /// <param name="d">字典</param>
        /// <param name="gt">替换类型</param>
        /// <param name="tabNum">空格数量</param>
        /// <returns>组合后的字符串</returns> 
        private string JoinByDictionary(Dictionary<string, string> d, GenerateType gt, int tabNum) {
            int i = 1;
            StringBuilder sb = new StringBuilder();
            foreach (string key in d.Keys) {
                switch (gt) {
                    case GenerateType.Parameter:
                        sb.AppendFormat("@{0} {1}", key, d[key]);
                        break;
                    case GenerateType.Insert:
                        sb.AppendFormat("{0}", key);
                        break;
                    case GenerateType.InsertAT:
                        sb.AppendFormat("@{0}", key);
                        break;
                    case GenerateType.Update:
                        sb.AppendFormat("{0}=@{0}", key);
                        break;
                    case GenerateType.Set:
                        sb.AppendFormat("@{0}={0}", key);
                        break;
                }
                if (i < d.Count) {
                    sb.AppendFormat(FormatSymbol.Comma);
                    if (GenerateType.Insert != gt && GenerateType.InsertAT != gt) {
                        sb.AppendFormat(FormatSymbol.CrLf);
                        sb.AppendFormat(GenerateHelper.GenerateTab(tabNum));
                    }
                }
                i++;
            }
            return sb.ToString();
        }

        #endregion
    }
}
